#-*- coding:UTF-8 -*-

from __future__ import division


import datetime

import sqlalchemy
import sqlalchemy.orm


from sqlalchemy import Column, Integer, String,DateTime, Binary, ForeignKey, Float, BigInteger
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base


Base=declarative_base()


class User(Base):
    __tablename__ = 'user'
    id              = Column(Integer,primary_key=True)
    name            = Column(String(32),unique=True)
    fullname        = Column(String(64))
    password        = Column(String(64))
    createtime      = Column(DateTime())
    updatetime      = Column(DateTime())
    mail            = Column(String(32))
    #isadmin         = Column(Integer, default=0)
    usergroups      = relationship('UserGroupMapping',back_populates='user')
    created_systems = relationship('System', back_populates='creator')
    created_hosts   = relationship('Host', back_populates='creator')

    def get_groups(self):
        if hasattr(self,'usergroups'):
            group_list = []
            for ug in self.usergroups:
                group_list.append(ug.group)
            return group_list
        return []

    def __repr__(self):
        return '<User id=%s,name=%s,fullname=%s>'%(self.id,self.name,self.fullname)

    def __eq__(self,other):
        return self.id == other.id

    def __dir__(self):
        return ['id','name','fullname']


class Group(Base):
    __tablename__ = 'group'
    id          = Column(Integer,primary_key=True)
    name        = Column(String(32),unique=True)
    description = Column(String(64))
    createtime  = Column(DateTime())
    updatetime  = Column(DateTime())
    groupusers  = relationship('UserGroupMapping',back_populates='group')

    def get_users(self):
        if hasattr(self,'groupusers'):
            user_list = []
            for ug in self.groupusers:
                user_list.append(ug.user)
            return user_list
        return []

    def __repr__(self):
        return '<Group id=%s,name=%s>'%(self.id,self.name)

    def __eq__(self,other):
        return self.id == other.id

    def __dir__(self):
        return ['id','name']


class UserGroupMapping(Base):
    __tablename__ = 'usergrouplink'
    user_id    = Column(Integer, ForeignKey('user.id'), primary_key=True)
    group_id   = Column(Integer, ForeignKey('group.id'), primary_key=True)
    note       = Column(String(128))
    createtime = Column(DateTime())
    updatetime = Column(DateTime())
    user       = relationship('User',back_populates='usergroups')
    group      = relationship('Group',back_populates='groupusers')
    def __repr__(self):
        return '<UserGroupMapping user_id=%s, group_id=%s>'%(self.user_id,self.group_id)

    def __eq__(self,other):
        return self.user_id == other.user_id and self.group_id == other.group_id


class System(Base):
    __tablename__ = 'system'
    id          = Column(Integer, primary_key=True)
    name        = Column(String(32),unique=True)
    description = Column(String(128), default='')
    createtime  = Column(DateTime())
    updatetime  = Column(DateTime())
    systype     = Column(String(32)) #Column(Integer, default=0) # dev / tst / pre /prd
    enabled     = Column(Integer, default=1) # enabled / disabled
    creator_id  = Column(Integer, ForeignKey('user.id'))
    creator     = relationship('User', back_populates='created_systems')
    wcapp       = relationship('WCApp', back_populates='system', uselist=False) # uselist means one to one relation
    #hosts       = relationship('Host', back_populates='system')
    systemhosts = relationship('SystemHostMapping',back_populates='system')

    def __repr__(self):
        return '<System id=%s,name=%s, enabled=%s>'%(self.id, self.name, self.enabled)

    def __eq__(self,other):
        return self.id == other.id

    def __dir__(self):
        return ['id', 'name', 'description']


class Host(Base):
    __tablename__ = 'host'
    id            = Column(Integer, primary_key=True)
    #ip            = Column(String(20),unique=True)
    ip            = Column(String(20)) # remove unique=True so that one host could belong to many sytems
    name          = Column(String(32))
    otherips      = Column(String(128), default='') # separated by ','
    #systemid      = Column(String(20))
    servertype    = Column(String(32))
    createtime    = Column(DateTime())
    updatetime    = Column(DateTime())
    ostype        = Column(String(16))
    enabled       = Column(Integer, default=1) # enabled / disabled
    creator_id    = Column(Integer, ForeignKey('user.id'))
    creator       = relationship('User', back_populates='created_hosts')
    #system_id     = Column(Integer, ForeignKey('system.id'))
    #system        = relationship('System',back_populates='hosts')
    auths         = relationship('Auth',back_populates='host')
    datacenter_id = Column(Integer, ForeignKey('datacenter.id'))
    datacenter    = relationship('DataCenter',back_populates='hosts')
    hostsystems   = relationship('SystemHostMapping',back_populates='host')
    '''
    cpustats   = relationship('CPUStats',back_populates='host')
    memstats   = relationship('MemStats',back_populates='host')
    diskstats  = relationship('DiskStats',back_populates='host')
    iostats    = relationship('IOStats',back_populates='host')
    '''

    def __repr__(self):
        if self.otherips:
            return '<Host id=%s, name=%s, ip=%s(%s), servertype=%s>'%(self.id, self.name, self.ip, self.otherips, self.servertype)
        else:
            return '<Host id=%s, name=%s, ip=%s, servertype=%s>'%(self.id, self.name, self.ip, self.servertype)

    def __eq__(self,other):
        return self.id == other.id

    def __dir__(self):
        return ['id','ip','name','ostype']


class SystemHostMapping(Base):
    __tablename__ = 'systemhostlink'
    system_id  = Column(Integer, ForeignKey('system.id'), primary_key=True)
    host_id    = Column(Integer, ForeignKey('host.id'), primary_key=True)
    note       = Column(String(128))
    createtime = Column(DateTime())
    updatetime = Column(DateTime())
    system     = relationship('System',back_populates='systemhosts')
    host       = relationship('Host',back_populates='hostsystems')
    def __repr__(self):
        return '<SystemHostMapping system_id=%s, host_id=%s>'%(self.system_id,self.host_id)

    def __eq__(self,other):
        return self.system_id == other.system_id and self.host_id == other.host_id


class Auth(Base):
    __tablename__ = 'osauth'
    id         = Column(Integer, primary_key=True)
    username   = Column(String(16))
    password   = Column(String(16))
    createtime = Column(DateTime())
    updatetime = Column(DateTime())
    can_sudo   = Column(Integer)
    host_id    = Column(Integer, ForeignKey('host.id'))
    host       = relationship('Host', back_populates='auths')
    def __repr__(self):
        return '<auth id=%s,username=%s,sudo=%s>'%(self.id,self.username,self.can_sudo)

    def __eq__(self,other):
        return self.id == other.id

    def __dir__(self):
        return ['id','username','password']


class WCApp(Base):
    __tablename__ = 'wcapp'
    id           = Column(Integer, primary_key=True)
    name         = Column(String(32))
    appadmin     = Column(String(32))
    apppass      = Column(String(32))
    url          = Column(String(512))
    createtime   = Column(DateTime())
    updatetime   = Column(DateTime())
    slavenumber  = Column(Integer)
    wthome       = Column(String(255))
    localwthome  = Column(String(255))
    localbackup  = Column(String(255))
    remotebackup = Column(String(255))
    envset       = Column(Binary())
    startcmd     = Column(Binary())
    stopcmd      = Column(Binary())

    system_id    = Column(Integer, ForeignKey('system.id'))
    system       = relationship('System',back_populates='wcapp')

    def __repr__(self):
        return '<WCApp id=%s,name=%s, appadmin=%s>'%(self.id, self.name, self.appadmin)

    def __eq__(self,other):
        return self.id == other.id

    def __dir__(self):
        return ['id', 'name', 'description']


class PermissionMapping(Base):
    __tablename__ = 'permissionlink'
    id         = Column(Integer, primary_key=True)
    createtime = Column(DateTime())
    updatetime = Column(DateTime())
    permission = Column(String(16))
    actor_id   = Column(Integer)
    actor_type = Column(String(64)) # user | group
    res_id     = Column(Integer)
    res_type   = Column(String(64)) # sys | host

    def __repr__(self):
        return '<PermissionMapping actor_id=%s, actor_type=%s, res_id=%s, res_type=%s>'%(self.actor_id, self.actor_type, self.res_id, self.res_type)

    def __eq__(self,other):
        return self.actor_id == other.actor_id and self.actor_type == other.actor_type and self.res_id == other.res_id and self.res_type == other.res_type


class DataCenter(Base):
    __tablename__ = 'datacenter'
    id         = Column(Integer, primary_key=True)
    name       = Column(String(32), unique=True)
    bandwidth  = Column(String(32))
    phone      = Column(String(32))
    address    = Column(String(128))
    createtime = Column(DateTime())
    updatetime = Column(DateTime())
    hosts      = relationship('Host', back_populates='datacenter')

    def __repr__(self):
        return '<DataCenter id=%s, name=%s>'%(self.id, self.name)

    def __eq__(self,other):
        return self.id == other.id

    def __dir__(self):
        return ['id', 'name', 'bandwidth', 'phone', 'address']

